package base;

import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

import org.apache.commons.collections.Closure;
import org.apache.commons.collections.CollectionUtils;

import base.check.Check;
import base.value.Value;



public class UserObject implements IUserObject {
	
	public class UserObjectContext {
		public UUID uuid;
	}
	
	public final UserObjectContext context = new UserObjectContext();
	private final List< Value<?> > values = new ArrayList< Value<?> >();

	public void addValue(Value<?> val) {
		Check.notNull(val, "value");
		Check.isTrue( values.add(val), Check.raiseException, "can't add value");
	}
	
	public boolean contsints(Value<?> val) {
		return values.contains(val);
	}
	
	public void removeValue(Value<?> val) {
		Check.notNull(val, "value");
		Check.isTrue( values.remove(val), Check.raiseException, "can't remove value");
	}

	public int size() {
		return values.size();
	}

	public Value<?> find(final IUserPredicate< Value<?> > predicate) {
		return (Value<?>) org.apache.commons.collections.CollectionUtils.find(values, new org.apache.commons.collections.Predicate() {
			@Override
			public boolean evaluate(Object object) {
				Value<?> v = (Value<?>) object;
				return predicate.evaluate(v);
			}
		});
	}

	public void findResults(final IUserPredicate< Value<?> > predicate, final List< Value<?> > result) {
		CollectionUtils.forAllDo(values, new Closure() {
		
			@Override
			public void execute(Object input) {
				Value<?> v = (Value<?>) input;
				if (predicate.evaluate(v)){
					result.add(v);
				}
			}
		});
	}
	
	public boolean containsValue(Value<?> value){
		Check.notNull(value, "value");
		
		return this.contsints(value);
	}
	
	public Value<?> findValue(IUserPredicate< Value<?> > predicate){
		Check.notNull(predicate, "predicate");
		
		return this.find(predicate);
	}
	
	public List< Value<?> > findValues(IUserPredicate< Value<?> > predicate){
		Check.notNull(predicate, "predicate");
		
		List< Value<?> > results = new ArrayList< Value<?> >();
		this.findResults(predicate, results);
		return results;
	}
	
	
	public static class Builder {
		private UserObject uo;
		
		public Builder(){
			this(null);
		}
		
		public Builder(UserObject setUo){
			uo = setUo;
		}

		public UserObject getUo() {
			return uo;
		}

		public Builder build(UserObject uo) {
			this.uo = uo;
			return this;
		}
		
		
		public Builder newUserObject(){
			uo = new UserObject();
			return this;
		}
		
		public Builder setUuid(UUID uuid){
			uo.context.uuid = uuid;
			return this;
		}
		
		public Builder addValue(Value<?> value){
			uo.addValue(value);
			return this;
		}
	}
	
	
	public static class FindTypePredicate implements IUserPredicate<Value<?>> {
		
		private final Class<?> type;

		public FindTypePredicate(Class<?> type) {
			Check.notNull(type, "type");
			this.type = type;
		}

		@Override
		public boolean evaluate(Value<?> t) {
			if (null != t && t.isHasType(type)){
				return true;
			}
			return false;
		}
	}
}
